package core

import (
	"gorm.io/driver/postgres"
	"gorm.io/gorm"
	"gorm.io/gorm/logger"
	"gorm.io/gorm/schema"
	"log"
	"os"
	"seven-admin/core/config"
	"time"
)

var db = initDB()

func GetDB() *gorm.DB {
	return db
}

func CloseDB() {
	sqlDB, err := db.DB()
	if err != nil {
		log.Fatal("initMysql db.DB err:", err)
	}
	err = sqlDB.Close()
	if err != nil {
		log.Fatal("initMysql db.DB Close err:", err)
	}
}

func initDB() *gorm.DB {
	slowThreshold := time.Second
	ignoreRecordNotFoundError := true
	logLevel := logger.Warn
	if config.Env.GinMode == "debug" {
		logLevel = logger.Info
		slowThreshold = 200 * time.Millisecond
		ignoreRecordNotFoundError = false
	}
	logg := logger.New(
		log.New(os.Stdout, "\r\n", log.LstdFlags), // io writer（日志输出的目标，前缀和日志包含的内容——译者注）
		logger.Config{
			SlowThreshold:             slowThreshold,             // 慢 SQL 阈值
			LogLevel:                  logLevel,                  // 日志级别
			IgnoreRecordNotFoundError: ignoreRecordNotFoundError, // 忽略ErrRecordNotFound（记录未找到）错误
			Colorful:                  true,                      // 彩色打印
		},
	)
	d, err := gorm.Open(postgres.New(postgres.Config{
		DSN:                  config.Env.DatabaseUrl,
		PreferSimpleProtocol: false, // disable implicit prepared statement (default is false)
	}), &gorm.Config{
		SkipDefaultTransaction: false, // 禁用默认事务
		NamingStrategy: schema.NamingStrategy{
			TablePrefix:   config.Env.DbTablePrefix, // 表名前缀
			SingularTable: false,                    // 使用单一表名, eg. `User` => `user`
		},
		DisableForeignKeyConstraintWhenMigrating: false, // 禁用自动创建外键约束
		Logger:                                   logg,  // 自定义Logger
	})
	if err != nil {
		panic("failed to connect database")
	}
	if config.Env.AutoMigrate {
		err := migrate(d)
		if err != nil {
			log.Fatal("AutoMigrate err:", err)
		}
	}
	sqlDB, err := d.DB()
	if err != nil {
		log.Fatal("initMysql db.DB err:", err)
	}
	// 数据库空闲连接池最大值
	sqlDB.SetMaxIdleConns(config.Env.DbMaxIdleConns)
	// 数据库连接池最大值
	sqlDB.SetMaxOpenConns(config.Env.DbMaxOpenConns)
	// 连接可复用的最大时间
	sqlDB.SetConnMaxLifetime(time.Duration(config.Env.DbConnMaxLifetimeHours) * time.Hour)

	return d
}

func DBTableName(model interface{}) string {
	stmt := &gorm.Statement{DB: db}
	stmt.Parse(model)
	return stmt.Schema.Table
}
